package com.dna.common.io;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import sun.reflect.generics.reflectiveObjects.NotImplementedException;

/**
 * Binder Class enables multi input streams (sources) and multi output streams (destinations) to be bound.
 * All datas coming from the input streams will be forwarded to the
 * output streams.
 * 
 * @author Patrick
 * @version 1.0
 *
 */
public class MultiStreamJack extends StreamJack {

	private List<StreamJack> binders;
	//TODO to be changed with a ThreadPool
	private List<Thread> threadPool = new ArrayList<Thread>();
	
	public MultiStreamJack(int bufferSize, InputStream... sources) {
		this(bufferSize, sources, new OutputStream[0]);
	}
	
	public MultiStreamJack(int bufferSize, InputStream[] sources, OutputStream... destinations) {
		binders = new ArrayList<StreamJack>();
		if(sources != null) {
			for(int i=0; i<sources.length; i++)
				binders.add(new StreamJack(bufferSize, sources[i], this));
		}
		if(destinations != null) {
			for(int j=0; j<destinations.length; j++)
				this.destinations.add(destinations[j]);
		}
	}
	
	@Override
	public Thread start() {
		for(StreamJack binder : binders)
			threadPool.add(binder.start());
		return null;
	}
	
	public Thread start(InputStream source) {
		for(int i=0; i<binders.size(); i++) {
			StreamJack binder = binders.get(i);
			if(binder.source.equals(source))
				return binder.start();
		}
		return null;
	}
	
	@Override
	public void stop() {
		for(StreamJack binder : binders)
			binder.stop();
	}
	
	public boolean stop(InputStream source) {
		for(int i=0; i<binders.size(); i++) {
			StreamJack binder = binders.get(i);
			if(binder.source.equals(source)) {
				binder.stop();
				return true;
			}
		}
		return false;
	}

	public void suspend() {
		for(StreamJack binder : binders)
			binder.suspend();
	}
	
	public boolean suspend(InputStream source) {
		for(int i=0; i<binders.size(); i++) {
			StreamJack binder = binders.get(i);
			if(binder.source.equals(source)) {
				if(binder.active) {
					binder.suspend();
					return true;
				}
				else
					return false;
			}
		}
		return false;
	}
	
	public void restart() {
		for(StreamJack binder : binders)
			binder.restart();
	}
	
	public boolean restart(InputStream source) {
		for(int i=0; i<binders.size(); i++) {
			StreamJack binder = binders.get(i);
			if(binder.source.equals(source)) {
				if(binder.suspend) {
					binder.restart();
					return true;
				}
				else
					return false;
			}
		}
		return false;
	}
	
	public boolean addInput(InputStream inputStream) {
		if(inputStream==null)
			return false;
		if(binders==null)
			binders = new ArrayList<StreamJack>();
		StreamJack binder = new StreamJack(bufferSize, inputStream, this);
		if(!binders.add(binder))
			return false;
		Thread thread = this.start(inputStream);
		return thread!=null;
	}
	
	@Override
	public void run() {
		throw new NotImplementedException();
	}
	
	@Override
	public synchronized void write(int i) throws IOException {
		super.write(i);
	}
	
	@Override
	public synchronized void write(byte[] abyte0) throws IOException {
		super.write(abyte0);
	}
	
	@Override
	public synchronized void write(byte[] abyte0, int i, int j) throws IOException {
		super.write(abyte0, i, j);
	}

}

